﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using umbraco.BusinessLogic;
using Microsoft.Practices.Unity;
using Core.Module.Interfaces.Model;
using Core.Module.Interfaces;
using Core.Module.Interfaces.Controller;
using umbraco.cms.businesslogic.web;
using umbraco.controls;
using System.Web.UI;
using Core.Module.StaticContent.umbraco.ism.modules;
using umbraco.uicontrols;
using umbraco;
using umbraco.cms.businesslogic;
using System.IO;
using System.Xml.Linq;
using System.Xml;
using System.Reflection;
using umbraco.BusinessLogic.Utils;
using umbraco.presentation;

namespace Core.Module
{
    public class CoreApplicationBace : ApplicationBase
    {
        public CoreApplicationBace()
        {
            InitMultiSiteSystem();

        }

        private void InitMultiSiteSystem()
        {
            InitModules();
            UmbracoDefault.BeforeRequestInit += new UmbracoDefault.RequestInitEventHandler(ChangeSitePageMaster);
            ContentControl.AfterContentControlLoad += new ContentControl.AfterContentControlLoadEventHandler(AddControlToEditModules);
            
            InitModuleTree();
            ChecWebConfiguration();
        }


        private void ChangeSitePageMaster(object sender, RequestInitEventArgs e)
        {
            
            IModuleNode node = Core.Module.Context.Frontend.Nodes.Get(UmbracoContext.Current.PageId.HasValue?UmbracoContext.Current.PageId.Value.ToString():"-1");
            Document d =new Document(true, int.Parse(node.Id));
            umbraco.cms.businesslogic.property.Property[] props = d.getProperties;
 
            ISite site = Core.Module.Context.Frontend.Sites.Get(node.SiteId);
            string smaster=Core.Module.Context.Frontend.Nodes.GetPropertyValue(site.Node, "siteMasterPage") as string ;
            if (!string.IsNullOrEmpty(smaster))
            {
                MasterPage mp=(e.Context.Handler as Page).Master;
                while(mp!=null && mp as Core.Module.Controls.SiteMasterPage==null)
                    mp=mp.Master;
                if (mp!=null) mp.MasterPageFile = smaster;
            };
        }

       

        #region Init Modules System...
        private void InitModules()
        {
            IModuleController<IFrontend> modules = Context.Frontend.Modules;
            List<ISite> Sites = Context.Frontend.Sites.Get();
            foreach (ISite site in Sites)
            {
                site.Modules = modules.Get(site);
                foreach (IModule mitem in site.Modules)
                    try
                    {
                        mitem.Site = site;
                        mitem.Init(site);
                    }
                    catch (Exception ex)
                    {
                        Log.Add(LogTypes.Error, -1, "can'tInit module:" + mitem.Alias + ", for site:" + site.Node.Alias + ".Error:" + ex.Message + "\r\n<br/>" + ex.StackTrace);
                    }
            }
        }
       

        private void InitModuleTree()
        {
            foreach (IApplication aitem in ObjectManager.ResolveAll<IApplication>())
                CheckAppRegistered(aitem);

            foreach (IApplicationTree atitem in ObjectManager.ResolveAll<IApplicationTree>())
                CheckTreeRegistered(atitem);
        }
        private void ChecWebConfiguration()
        {
            XmlDocument xdoc = new XmlDocument();

            xdoc.Load(FilePath);
            XmlNodeList xcontrols = xdoc.SelectNodes("//system.web/pages/controls");
            string thisAssembly = Assembly.GetAssembly(typeof(CoreApplicationBace)).FullName;
            bool beenModified = false;
            foreach (XmlElement item in xcontrols)
            {
                XmlElement nodeAdd = item.SelectSingleNode("add[@tagPrefix='module' and @namespace='Core.Module.Controls']") as XmlElement;
                if (nodeAdd == null)
                {
                    nodeAdd = xdoc.CreateElement("add");
                    nodeAdd.SetAttribute("tagPrefix", "module");
                    nodeAdd.SetAttribute("namespace", "Core.Module.Controls");
                    nodeAdd.SetAttribute("assembly", thisAssembly);
                    item.AppendChild(nodeAdd);
                    beenModified = true;
                }
            }
            if (beenModified) xdoc.Save(FilePath);
        }

        private void CheckAppRegistered(IApplication aitem)
        {
            Application app = umbraco.BusinessLogic.Application.getByAlias(aitem.Alias);
            if (app == null)
            {
                Application.MakeNew(aitem.Name, aitem.Alias, aitem.Icon);
                app = umbraco.BusinessLogic.Application.getByAlias(aitem.Alias);
                if (app == null) return;
                foreach (User u in User.getAll())
                    if (u.IsAdmin()) u.addApplication(aitem.Alias);
            }
        }

        private void CheckTreeRegistered(IApplicationTree aTree)
        {
            ApplicationTree tree = ApplicationTree.getApplicationTree(aTree.Application).Where(ti => ti.Alias.Equals(aTree.Alias, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
            if (tree == null) tree = ApplicationTree.getByAlias(aTree.Alias);
            if (tree == null)
            {
                Type t = aTree.GetType();
                string aname = t.Assembly.GetName().Name;
                string tname = t.FullName.Substring(aname.Length + 1);
                ApplicationTree.MakeNew(true, true, aTree.OrderNr, aTree.Application, aTree.Alias, ui.GetText("tree", aTree.Alias), aTree.Icon, aTree.IconOpen, aname, tname, "");
                tree = ApplicationTree.getApplicationTree(aTree.Application).Where(ti => ti.Alias.Equals(aTree.Alias, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
            };
            if (tree == null) return;

        }


        void AddControlToEditModules(ContentControl contentControl, ContentControlLoadEventArgs e)
        {
            ISite curSite = Context.Frontend.Sites.Get().Where(si => si.Node.Id.Equals(contentControl.ContentObject.Id.ToString())).SingleOrDefault();
            if (curSite == null) return;
            curSite.Modules = Context.Frontend.Modules.Get(curSite);
            EditSiteModules control = contentControl.Page.LoadControl("/umbraco/ism/modules/editsitemodules.ascx") as EditSiteModules;
            control.ForSite = curSite;
            control.UserCouldEditModules = true;
            Pane modulesPane = new Pane();
            modulesPane.addProperty(umbraco.ui.Text("multisite", "editmodules property"), control);
            contentControl.tpProp.Controls.Add(modulesPane);

            foreach (TabPage item in contentControl.GetPanels())
            {
                item.Menu.InsertSplitter();
                MenuImageButton menuEditModules = item.Menu.NewImageButton();
                menuEditModules.ID = item.ID + "_editModules";
                menuEditModules.ImageUrl = "/umbraco/images/editor/editmodules.png";
                menuEditModules.Click += new ImageClickEventHandler((s, eclick) => { menuEditModules_Click(curSite, s, eclick); });
                menuEditModules.OnClickCommand = "invokeEditModulesHandlers();";
                menuEditModules.AltText = ui.Text("multisite", "editmodules menubutton", null);
            }
        }
        void menuEditModules_Click(ISite site, object sender, ImageClickEventArgs e)
        {
            umbraco.BasePages.BasePage.Current.ClientTools.OpenModalWindow(string.Format("/umbraco/ism/modules/editmodules.aspx?site={0}", site.Node.Id), "Edit Modules Settings for site:" + site.Node.Name, true, 780, 600, 0, 0, "", "");
            umbraco.BasePages.BasePage.Current.ClientTools.ShowSpeechBubble(umbraco.BasePages.BasePage.speechBubbleIcon.info, "module editor info", "all changes are storing right after you press save button...");
        }

        private string FilePath
        {
            get
            {
                return string.Concat(new object[] { GlobalSettings.FullpathToRoot, Path.DirectorySeparatorChar, "web.config" });
            }
        }
        #endregion

    }
}
